﻿using System;
using System.Windows;
using System.Windows.Threading;
using log4net;
using UI.Dialogs;
using AutoMapper;
using DataStore.Domain;
using Infrastructure.ViewModels;
using System.Threading.Tasks;

namespace UI
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Application.Startup"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.StartupEventArgs"/> that contains the event data.</param>
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            // Run bootstrapper
            Bootstrapper bootstrapper = new Bootstrapper();
            bootstrapper.Run();

            // AutoMapper mappings
            Parallel.Invoke(CreateAutoMapperMappings);
        }

        /// <summary>
        /// Creates the AutoMapper mappings.
        /// </summary>
        private static void CreateAutoMapperMappings()
        {
            // Cloning
            Mapper.CreateMap<Book, Book>();
            Mapper.CreateMap<BookViewModel, BookViewModel>();
            Mapper.CreateMap<CatalogItem, CatalogItem>().Include<Book, Book>();
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Application.Exit"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.Windows.ExitEventArgs"/> that contains the event data.</param>
        protected override void OnExit(ExitEventArgs e)
        {
            
            ILog log = Infrastructure.CurrentData.Current.Container.Resolve<ILog>();
            if (log.IsInfoEnabled)
            {
                log.Info("Application closed");
            }

            base.OnExit(e);
        }

        /// <summary>
        /// Handles the UnhandledException event of the CurrentDomain.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.UnhandledExceptionEventArgs"/> instance containing the event data.</param>
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception exception = e.ExceptionObject as Exception;

            LogFatalException(exception);
            ShowExceptionDialog(exception);
        }

        /// <summary>
        /// Unexpected exception handler
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Threading.DispatcherUnhandledExceptionEventArgs"/> instance containing the event data.</param>
        static void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            LogFatalException(e.Exception);
            
            ExceptionDialog dialog = ShowExceptionDialog(e.Exception);
            if(dialog.CanContinue)
            {
                e.Handled = true;
            }
            else
            {
                Environment.Exit(-1);
            }
        }

        /// <summary>
        /// Shows the unhandled exception dialog.
        /// </summary>
        /// <param name="ex">The exception.</param>
        /// <returns>The dialog box shown on screen.</returns>
        private static ExceptionDialog ShowExceptionDialog(Exception ex)
        {
            ExceptionDialog dialog = new ExceptionDialog();
            if (Current.MainWindow != dialog && Current.MainWindow.Visibility == Visibility.Visible)
            {
                dialog.Owner = Current.MainWindow;
            }
            dialog.Exception = ex;
            dialog.ShowDialog();

            return dialog;
        }

        /// <summary>
        /// Logs the fatal (unhandled) exception.
        /// </summary>
        /// <param name="ex">The exception.</param>
        private static void LogFatalException(Exception ex)
        {
            try
            {
                ILog log = Infrastructure.CurrentData.Current.Container.Resolve<ILog>();
                if (log.IsFatalEnabled)
                {
                    log.Fatal(string.Format("Unhandled exception: {0}", ex.Message), ex);
                }
            }
// ReSharper disable EmptyGeneralCatchClause
            catch {}
// ReSharper restore EmptyGeneralCatchClause
        }
    }
}
